/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.siseventos.util;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.log4j.Logger;

/**
 * Classe usada para facilitar a geração de Relatório a partir da aplicação
 *
 * @author marcosnatanpacheco
 */
public class RelatorioHelper {
    // Logger

    private static Logger log = Logger.getLogger(RelatorioHelper.class);
    // Campos
    private static Properties connProps;
    private static Map<String, String> relPathMaps;
    public static final String REL_EVENTO_POR_PERIODO = "1";
    public static final String REL_EVENTO_POR_TIPO_EVENTO = "2";
    public static final String REL_EVENTO_POR_PUBLICO = "3";
    public static final String REL_ATIVIDADES_PARA_UM_EVENTO = "4";
    public static final String REL_ATIVIDADES_POR_DATA = "5";
    public static final String REL_ATIVIDADES_POR_TIPO = "6";
    public static final String REL_ATIVIDADES_POR_LOCAL = "7";
    public static final String REL_APROVACAO_LOCAL_POR_USUARIO = "8";
    public static final String REL_APROVACAO_RECURSO_POR_USUARIO = "9";
    public static final String REL_APROVACAO_SERVICOS_POR_USUARIO = "10";
    public static final String REL_HISTORICO_APROVACAO_POR_USUARIO = "11";
    public static final String REL_RECURSOS_MAIS_UTILIZADOS = "12";
    public static final String REL_SERVICOS_MAIS_UTILIZADOS = "13";
    public static final String REL_PARTICIPANTES = "14";
    public static final String REL_AVALIACAO_POR_PARTICIPANTE = "15";
    public static final String REL_AVALIACOES_POR_EVENTO = "16";
    public static final String REL_TODOS_EVENTOS_ATIVIDADES_POR_PERIODO = "17";
    public static final String REL_PROMOTORES = "18";
    public static final String PDF_MEDIATYPE = "application/pdf";

    // Construtor estático
    static {
        // Inicializando os mapeamentos
        relPathMaps = new HashMap<String, String>() {

            {
                put(REL_EVENTO_POR_PERIODO, "siseventos_rel_evento_por_periodo.jasper");
                put(REL_EVENTO_POR_TIPO_EVENTO,"siseventos_rel_evento_por_tipo.jasper");
                put(REL_EVENTO_POR_PUBLICO,"siseventos_rel_evento_por_publico.jasper");
                put(REL_ATIVIDADES_PARA_UM_EVENTO,"siseventos_rel_atividades_para_um_evento.jasper");
                put(REL_ATIVIDADES_POR_DATA,"siseventos_rel_atividades_por_data.jasper");
                put(REL_ATIVIDADES_POR_TIPO,"siseventos_rel__atividades_por_tipo.jasper");
                put(REL_ATIVIDADES_POR_LOCAL,"siseventos_rel__atividades_por_local.jasper");
                put(REL_APROVACAO_LOCAL_POR_USUARIO,"siseventos_rel_aprovacao_local_por_funcionario.jasper");
                put(REL_APROVACAO_RECURSO_POR_USUARIO,"siseventos_rel_aprovacao_recurso_por_funcionario.jasper");
                put(REL_APROVACAO_SERVICOS_POR_USUARIO,"siseventos_rel_aprovacao_servicos_por_funcionario.jasper");
                put(REL_HISTORICO_APROVACAO_POR_USUARIO,"siseventos_rel_historico_aprovacao_por_funcionario.jasper");
                put(REL_RECURSOS_MAIS_UTILIZADOS,"siseventos_rel_recursos_mais_utilizados.jasper");
                put(REL_SERVICOS_MAIS_UTILIZADOS,"siseventos_rel_servicos_mais_utilizados.jasper");
                put(REL_PARTICIPANTES,"siseventos_rel_participantes.jasper");
                put(REL_AVALIACAO_POR_PARTICIPANTE,"siseventos_rel_avaliacao_por_participante.jasper");
                put(REL_AVALIACOES_POR_EVENTO,"siseventos_rel_master.jasper");
                put(REL_TODOS_EVENTOS_ATIVIDADES_POR_PERIODO,"siseventos_rel_todos_eventos_atividades.jasper");
                put(REL_PROMOTORES,"siseventos_rel_promotores.jasper");
            }
        };

        // Buscando dados do arquivo de configuração da conexão  (db.properties)
        setupConfig("database.properties");
    }

    // Serviço
    public static void gerarRelatorio(String nomeFinal, String nomeRelatorio, Map<String, Object> parametros, Connection conexao, FacesContext contexto) throws FileNotFoundException, JRException, Exception {
        // Buscando o nome e o path do relatório
        String nome = relPathMaps.get(nomeRelatorio);
        
        // Adicionando a imagem
        parametros.put("LOGO_SISEVENTOS", getLogoPath("/resources/images/logoSisEventos.jpg", contexto));
        String pathRelatorio = pathRelatorio(contexto, nome);
        if (nome == null) {
            throw new Exception("Nome do relatório não informado.");
        }
        // Montando o objeto JasperReport
        JasperReport rel = null;
        JasperPrint relCompilado = null;
        byte[] relatorio = null;
        // Montando o objeto JasperPrint
        try {
            // Montando o objeto em memória
            rel = montarRelatorio(pathRelatorio);
            // Compilando o relatório
            relCompilado = carregarRelatorio(rel, parametros, conexao);
            // Fazendo o download do relatório
            downloadRelatorio(nomeFinal, relCompilado, contexto);
        } catch (Exception e) {
            Logger log = Logger.getLogger(RelatorioHelper.class);
            log.error(e.getMessage());
            throw e;
        }
    }

    public static byte[] gerarRelatorio(String path, Map<String, Object> parametros, JRBeanCollectionDataSource data) throws FileNotFoundException, JRException, Exception {
        // Montando o objeto JasperReport
        JasperReport rel = null;
        JasperPrint relCompilado = null;
        byte[] pdf = null;
        // Montando o objeto JasperPrint
        try {
            rel = montarRelatorio(path);
            relCompilado = JasperFillManager.fillReport(rel, parametros, data);
            pdf = JasperExportManager.exportReportToPdf(relCompilado);
        } catch (Exception e) {
            throw e;
        }
        // Exportando o objeto JasperPrint para um array de bytes
        return pdf;
    }

    public static Connection getConexao() throws Exception {
        // Lendo as configurações do arquivo de configuração
        String driver = connProps.getProperty("driverClass");
        String url = connProps.getProperty("url");
        String usuario = connProps.getProperty("username");
        // Registrando o Driver Mysql
        Class.forName(driver);

        // Buscando a conexão
        Connection conexao = null;
        try {
            conexao = DriverManager.getConnection(url, usuario, "");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw e;
        }
        return conexao;
    }

    public static String pathRelatorio(FacesContext contexto, String nomeRelatorio) {
        String relPath = contexto.getExternalContext().getRealPath("/resources/relatorios");
        String sufixo = (nomeRelatorio.endsWith(".jasper")) ? "" : ".jasper";
        return relPath.concat("/" + nomeRelatorio + sufixo);
    }

    public static void downloadRelatorio(String nomeRelatorio, JasperPrint jasperPrint, FacesContext contexto) throws IOException, JRException {
        try {
            // Setando a flag de ResponseComplete
            HttpServletResponse response = (HttpServletResponse) contexto.getExternalContext().getResponse();
            // Verificando o sufixo a ser adicionado
            String sufixo = (nomeRelatorio.endsWith(".pdf")) ? "" : ".pdf";
            response.reset();
            response.setHeader("Content-Disposition", "attachment;filename=" + nomeRelatorio + sufixo);
            response.setContentType(PDF_MEDIATYPE);

            OutputStream out = response.getOutputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            JasperExportManager.exportReportToPdfStream(jasperPrint, baos);
            baos.writeTo(out);

            out.flush();

            contexto.responseComplete();
        } catch (Exception e) {
            log.error("ERRO   :(");
        }

        log.warn("FIM   :)");
    }

    public static String getLogoPath(String virtualPath, FacesContext context) {
        return context.getExternalContext().getRealPath(virtualPath);
    }
    // Métodos privados

    private static void setupConfig(String nomeArquivo) {
        // Inicializando as propriedades da conexão
        connProps = new Properties();

        // Carregando as configurações a partir do arquivo
        try {
            InputStream resourceStream = RelatorioHelper.class.getClassLoader().getResourceAsStream(nomeArquivo);
            connProps.load(resourceStream);
        } catch (Exception e) {
            String x = e.getMessage();
        }
    }

    private static JasperReport montarRelatorio(String caminho) throws FileNotFoundException, JRException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(caminho));
        return (JasperReport) JRLoader.loadObject(bis);
    }

    private static JasperPrint carregarRelatorio(JasperReport relatorio, Map<String, Object> parametros, Connection conexao) throws JRException {
        return JasperFillManager.fillReport(relatorio, parametros, conexao);
    }
}
